From b9c2b46e3379204eba258715a470f84668469f3f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Nov 2014 09:25:25 -0800 Subject: [PATCH] Fix cross compiling with a build script Previously there was a mixup of where the build script was getting compiled into as well as where the output was going to. This commit fixes the problems for now, but still has room for improvement in the future. Build scripts themselves are now unconditionally built into `target/build/..` because they're compiled for the host platform. Their outputs are in `target/$target/build/..` as expected. --- src/cargo/ops/cargo_rustc/custom_build.rs | 18 ++++++---- tests/test_cargo_cross_compile.rs | 42 +++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index c11c64f6b..e5d3d7859 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -10,7 +10,7 @@ use util::{CargoResult, CargoError, human}; use util::{internal, ChainError, Require}; use super::job::Work; -use super::{fingerprint, process, KindHost, Context}; +use super::{fingerprint, process, KindTarget, KindHost, Context}; use util::Freshness; /// Contains the parsed output of a custom build script. @@ -31,12 +31,15 @@ pub struct BuildState { /// Prepares a `Work` that executes the target as a custom build script. pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) -> CargoResult<(Work, Work, Freshness)> { + // TODO: this shouldn't explicitly pass `KindTarget` for the layout, we + // may be running a build script for a plugin dependency. let (script_output, old_script_output, build_output, old_build_output) = { - let layout = cx.layout(pkg, KindHost); - (layout.build(pkg), - layout.proxy().old_build(pkg), - layout.build_out(pkg), - layout.proxy().old_build(pkg).join("out")) + let target = cx.layout(pkg, KindTarget); + let host = cx.layout(pkg, KindHost); + (host.build(pkg), + host.proxy().old_build(pkg), + target.build_out(pkg), + target.proxy().old_build(pkg).join("out")) }; // Building the command to execute @@ -92,7 +95,8 @@ pub fn prepare(pkg: &Package, target: &Target, cx: &mut Context) script_output.clone(), old_build_output.clone(), build_output.clone()); - try!(fs::mkdir(&script_output, USER_RWX)); + try!(fs::mkdir_recursive(&cx.layout(pkg, KindTarget).build(pkg), USER_RWX)); + try!(fs::mkdir_recursive(&cx.layout(pkg, KindHost).build(pkg), USER_RWX)); // Prepare the unit of "dirty work" which will actually run the custom build // command. diff --git a/tests/test_cargo_cross_compile.rs b/tests/test_cargo_cross_compile.rs index cc5745b0d..57ed1418c 100644 --- a/tests/test_cargo_cross_compile.rs +++ b/tests/test_cargo_cross_compile.rs @@ -474,3 +474,45 @@ test!(cross_but_no_dylibs { .with_stderr("dylib outputs are not supported for \ arm-apple-ios")); }) + +test!(cross_with_a_build_script { + if disabled() { return } + + let target = alternate(); + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + build = 'build.rs' + "#) + .file("build.rs", format!(r#" + use std::os; + fn main() {{ + assert_eq!(os::getenv("TARGET").unwrap().as_slice(), "{0}"); + let mut path = Path::new(os::getenv("OUT_DIR").unwrap()); + assert_eq!(path.filename().unwrap(), b"out"); + path.pop(); + assert!(path.filename().unwrap().starts_with(b"foo-")); + path.pop(); + assert_eq!(path.filename().unwrap(), b"build"); + path.pop(); + assert_eq!(path.filename().unwrap(), b"{0}"); + path.pop(); + assert_eq!(path.filename().unwrap(), b"target"); + }} + "#, target).as_slice()) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("--target").arg(&target).arg("-v"), + execs().with_status(0) + .with_stdout(format!("\ +{compiling} foo v0.0.0 (file://[..]) +{running} `rustc build.rs [..] --out-dir {dir}{sep}target{sep}build{sep}foo-[..]` +{running} `{dir}{sep}target{sep}build{sep}foo-[..]build-script-build` +{running} `rustc {dir}{sep}src{sep}main.rs [..] --target {target} [..]` +", compiling = COMPILING, running = RUNNING, target = target, + dir = p.root().display(), sep = path::SEP).as_slice())); +}) + -- 2.30.2